﻿using System.IO;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Sidvall.UI.Wpf
{
    public static class ControlManager
    {
        #region Public Members

        #region CopyToClipboard

        public static void CopyToClipboard(FrameworkElement item, System.Windows.Media.Brush background)
        {
            if (item == null)
                return;
            CopyToClipboard(item, (int)item.ActualWidth, (int)item.ActualHeight, background);
        }
        public static void CopyToClipboard(System.Windows.Media.Visual item, int width, int height, System.Windows.Media.Brush background)
        {
            RenderTargetBitmap bitmap;

            bitmap = GetBitmapSource(item, width, height, background);
            if (bitmap != null)
                Clipboard.SetImage(bitmap);
        }

        #endregion
        #region FindParentControl

        public static T FindParentControl<T>(System.Windows.DependencyObject child) where T : System.Windows.DependencyObject
        {
            System.Windows.DependencyObject parentObject;
            T parent;

            if (child == null)
                return null;

            parentObject = null;
            if (child is System.Windows.Media.Visual || child is System.Windows.Media.Media3D.Visual3D)
            {
                var contentControl = child as System.Windows.Controls.ContentControl;
                if (contentControl != null)
                    parentObject = contentControl.Parent;
                if (parentObject == null)
                    parentObject = System.Windows.Media.VisualTreeHelper.GetParent(child);
                if (parentObject == null)
                    parentObject = System.Windows.LogicalTreeHelper.GetParent(child);
            }
            else
                parentObject = System.Windows.LogicalTreeHelper.GetParent(child);
            if (parentObject == null)
                return null;

            parent = parentObject as T;
            if (parent != null)
                return parent;
            else
                return FindParentControl<T>(parentObject);
        }
        public static T FindParentControl<T>(System.Windows.UIElement reference, System.Windows.Point point) where T : System.Windows.DependencyObject
        {
            if (reference == null)
                return null;
            var element = reference.InputHitTest(point) as System.Windows.DependencyObject;
            if (element == null)
                return null;
            else if (element is T)
                return (T)element;
            else
                return FindParentControl<T>(element);
        }

        #endregion
        #region GetBitmapEncoder

        public static BitmapEncoder GetBitmapEncoder(ImageType imageType, FrameworkElement item, System.Windows.Media.Brush background)
        {
            if (item == null)
                return null;
            return GetBitmapEncoder(imageType, item, (int)item.ActualWidth, (int)item.ActualHeight, background);
        }
        public static BitmapEncoder GetBitmapEncoder(ImageType imageType, System.Windows.Media.Visual item, int width, int height, System.Windows.Media.Brush background)
        {
            BitmapEncoder image;
            RenderTargetBitmap bitmap;

            if (item == null)
                return null;
            bitmap = GetBitmapSource(item, width, height, background);
            image = GetBitmapEncoder(imageType);
            image.Frames.Add(BitmapFrame.Create(bitmap));
            return image;
        }
        private static BitmapEncoder GetBitmapEncoder(ImageType imageType)
        {
            PngBitmapEncoder pngImage;
            JpegBitmapEncoder jpegImage;
            BmpBitmapEncoder bmpImage;
            TiffBitmapEncoder tiffImage;
            WmpBitmapEncoder wmpImage;

            switch (imageType)
            {
                case ImageType.Bmp:
                    bmpImage = new BmpBitmapEncoder();
                    return bmpImage;
                case ImageType.Png:
                    pngImage = new PngBitmapEncoder();
                    return pngImage;
                case ImageType.Jpeg:
                    jpegImage = new JpegBitmapEncoder();
                    jpegImage.QualityLevel = 100;
                    return jpegImage;
                case ImageType.Tiff:
                    tiffImage = new TiffBitmapEncoder();
                    return tiffImage;
                case ImageType.Wmp:
                    wmpImage = new WmpBitmapEncoder();
                    return wmpImage;
                default:
                    throw new System.ArgumentException("Unknown image type");
            }
        }

        #endregion
        #region GetBitmapSource

        public static RenderTargetBitmap GetBitmapSource(FrameworkElement item, System.Windows.Media.Brush background)
        {
            if (item == null)
                return null;
            return GetBitmapSource(item, (int)item.ActualWidth, (int)item.ActualHeight, background);
        }
        public static RenderTargetBitmap GetBitmapSource(System.Windows.Media.Visual item, int width, int height, System.Windows.Media.Brush background)
        {
            RenderTargetBitmap bitmap;

            if (item == null)
                return null;
            bitmap = new RenderTargetBitmap(width, height, 96, 96, System.Windows.Media.PixelFormats.Pbgra32);
            if (background != null)
            {
                var rectangle = new Rectangle()
                {
                    Width = width,
                    Height = height,
                    Fill = background,
                };
                var size = new Size(width, height);
                rectangle.Measure(size);
                rectangle.Arrange(new Rect(size));
                bitmap.Render(rectangle);
            }
            bitmap.Render(item);

            return bitmap;
        }

        #endregion
        #region GetImage

        public static System.Drawing.Image GetImage(ImageType imageType, FrameworkElement item, System.Windows.Media.Brush background)
        {
            if (item == null)
                return null;
            return GetImage(imageType, item, (int)item.ActualWidth, (int)item.ActualHeight, background);
        }
        public static System.Drawing.Image GetImage(ImageType imageType, System.Windows.Media.Visual item, int width, int height, System.Windows.Media.Brush background)
        {
            var content = Sidvall.UI.Wpf.ControlManager.GetBitmapEncoder(imageType, item, width, height, background);
            if (content == null)
                return null;
            using (var stream = new MemoryStream())
            {
                content.Save(stream);
                return System.Drawing.Bitmap.FromStream(stream);
            }
        }

        #endregion
        #region GetFocusedBinding

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
        public static System.Windows.Data.BindingExpression GetFocusedBinding()
        {
            var textBox = System.Windows.Input.Keyboard.FocusedElement as System.Windows.Controls.TextBox;
            if (textBox != null)
                return textBox.GetBindingExpression(System.Windows.Controls.TextBox.TextProperty);
            return null;
        }

        #endregion
        #region SetLanguage

        public static void SetLanguage(FrameworkElement item)
        {
            SetLanguage(item, System.Globalization.CultureInfo.CurrentCulture);
        }
        public static void SetLanguage(FrameworkElement item, System.Globalization.CultureInfo culture)
        {
            var language = System.Windows.Markup.XmlLanguage.GetLanguage(culture.Name);
            var codeManager = Sidvall.SystemContext.Current.CodeManager;
            if (codeManager == null)
                codeManager = new Sidvall.Reflection.CodeManager(null);
            codeManager.SetFieldValue(language, culture, "_compatibleCulture");
            item.Language = language;
        }

        #endregion
        #region UpdateFocusedElement

        public static void UpdateFocusedElement()
        {
            var binding = GetFocusedBinding();
            if (binding == null)
                return;
            binding.UpdateSource();
        }

        #endregion

        #endregion
    }
}
